package com.huixh.train.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huixh.train.business.domain.*;
import com.huixh.train.business.enums.SeatTypeEnum;
import com.huixh.train.business.enums.TrainTypeEnum;
import com.huixh.train.business.mapper.DailyTrainSeatMapper;
import com.huixh.train.business.mapper.DailyTrainTicketMapper;
import com.huixh.train.business.req.DailyTrainTicketQueryReq;
import com.huixh.train.business.req.DailyTrainTicketSaveReq;
import com.huixh.train.business.resp.DailyTrainTicketQueryResp;
import com.huixh.train.business.service.DailyTrainTicketService;
import com.huixh.train.business.service.TrainStationService;
import com.huixh.train.common.resp.PageResult;
import com.huixh.train.utils.random.SnowUtil;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @author huixh
*/
@Service
public class DailyTrainTicketServiceImpl implements DailyTrainTicketService {

    private final Logger logger = LoggerFactory.getLogger(DailyTrainTicketServiceImpl.class);
    @Resource
    private DailyTrainTicketMapper dailyTrainTicketMapper;
    @Resource
    private TrainStationService trainStationService;
    @Resource
    private DailyTrainSeatMapper dailyTrainSeatMapper;
    @Resource
    private SnowUtil snowUtil;

    @Override
    public void save(DailyTrainTicketSaveReq dailyTrainTicketSaveReq) {
        DateTime now = DateTime.now();
        DailyTrainTicket dailyTrainTicket = BeanUtil.copyProperties(dailyTrainTicketSaveReq, DailyTrainTicket.class);
        if (ObjectUtil.isNull(dailyTrainTicket.getId())) {
            dailyTrainTicket.setId(snowUtil.getSnowflakeToLong());
            dailyTrainTicket.setCreateTime(now);
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.insert(dailyTrainTicket);
        } else {
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.updateByPrimaryKey(dailyTrainTicket);
        }
    }

    @Override
    public PageResult <List<DailyTrainTicketQueryResp>> queryList(DailyTrainTicketQueryReq dailyTrainTicketQueryReq) {
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.setOrderByClause("train_code asc, start_index asc");
        DailyTrainTicketExample.Criteria criteria = dailyTrainTicketExample.createCriteria();

        if (StrUtil.isNotBlank(dailyTrainTicketQueryReq.getTrainCode())){
            criteria.andTrainCodeEqualTo(dailyTrainTicketQueryReq.getTrainCode());
        }

        if (ObjectUtil.isNotNull(dailyTrainTicketQueryReq.getDate())){
            criteria.andDateEqualTo(dailyTrainTicketQueryReq.getDate());
        }

        if (StrUtil.isNotBlank(dailyTrainTicketQueryReq.getStartTrain())) {
            criteria.andStartEqualTo(dailyTrainTicketQueryReq.getStartTrain());
        }

        if (StrUtil.isNotBlank(dailyTrainTicketQueryReq.getEndTrain())) {
            criteria.andEndEqualTo(dailyTrainTicketQueryReq.getEndTrain());
        }
        logger.info("查询页码：{}", dailyTrainTicketQueryReq.getPageNum());
        logger.info("每页条数：{}", dailyTrainTicketQueryReq.getPageSize());
        PageHelper.startPage(dailyTrainTicketQueryReq.getPageNum(), dailyTrainTicketQueryReq.getPageSize());
        List<DailyTrainTicket> dailyTrainTickets = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);
        PageInfo<DailyTrainTicket> pageInfo = new PageInfo<>(dailyTrainTickets);
        logger.info("总行数：{}", pageInfo.getTotal());
        logger.info("总页数：{}", pageInfo.getPages());

        List<DailyTrainTicketQueryResp> list = BeanUtil.copyToList(dailyTrainTickets, DailyTrainTicketQueryResp.class);
        return PageResult.success(pageInfo.getTotal(), list);
    }

    @Override
    public void delete(Long id) {
        dailyTrainTicketMapper.deleteByPrimaryKey(id);
    }

    /**
     * 生成余票信息
     *
     * @param date 时间
     * @param train 车次
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void genDailyTrainTicket(Date date, Train train) {
        String trainCode = train.getCode();
        DateTime now = DateTime.now();
        logger.info("生成日期：【{}】车次【{}】余票信息开始", DateUtil.formatDate(date),train.getCode());
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.createCriteria()
                .andTrainCodeEqualTo(train.getCode())
                .andDateEqualTo(date);
        dailyTrainTicketMapper.deleteByExample(dailyTrainTicketExample);
        // 查询途径车站信息
        List<TrainStation> trainStations = trainStationService.selectByTrainCode(trainCode);
        if (CollUtil.isEmpty(trainStations)) {
            logger.info("车次【{}】没有车站信息，无法生成余票信息", trainCode);
        }
        List<DailyTrainTicket> dailyTrainTicketList = new ArrayList<>(8);
        for (int i = 0; i < trainStations.size(); i++) {
            TrainStation trainStationStart = trainStations.get(i);
            BigDecimal sumKm = BigDecimal.ZERO;
            for (int j = i+1; j < trainStations.size(); j++) {
                //计算里程只和
                sumKm = sumKm.add(trainStationStart.getKm());
                TrainStation trainStationEnd = trainStations.get(j);
                DailyTrainTicket dailyTrainTicket = new DailyTrainTicket();
                dailyTrainTicket.setId(snowUtil.getSnowflakeToLong());
                dailyTrainTicket.setDate(date);
                dailyTrainTicket.setTrainCode(trainCode);
                dailyTrainTicket.setStart(trainStationStart.getName());
                dailyTrainTicket.setStartPinyin(trainStationStart.getNamePinyin());
                dailyTrainTicket.setStartTime(trainStationStart.getOutTime());
                dailyTrainTicket.setStartIndex(trainStationStart.getIndex());
                dailyTrainTicket.setEnd(trainStationEnd.getName());
                dailyTrainTicket.setEndPinyin(trainStationEnd.getNamePinyin());
                dailyTrainTicket.setEndTime(trainStationEnd.getInTime());
                dailyTrainTicket.setEndIndex(trainStationEnd.getIndex());
                int firstClass = Math.toIntExact(countSeat(date, trainCode, SeatTypeEnum.YDZ.getCode()));
                int secondClass = Math.toIntExact(countSeat(date, trainCode, SeatTypeEnum.EDZ.getCode()));
                int softSleeper = Math.toIntExact(countSeat(date, trainCode, SeatTypeEnum.RW.getCode()));
                int hardSleeper = Math.toIntExact(countSeat(date, trainCode, SeatTypeEnum.YW.getCode()));
                dailyTrainTicket.setYdz(firstClass);
                // 计算票价 票价 = 里程之和 * 座位单价 * 车次类型系数
                dailyTrainTicket.setYdzPrice(sumKm.multiply(SeatTypeEnum.YDZ.getVal()).multiply(TrainTypeEnum.getPrice(train.getType())));
                dailyTrainTicket.setEdz(secondClass);
                dailyTrainTicket.setEdzPrice(sumKm.multiply(SeatTypeEnum.EDZ.getVal()).multiply(TrainTypeEnum.getPrice(train.getType())));
                dailyTrainTicket.setRw(softSleeper);
                dailyTrainTicket.setRwPrice(sumKm.multiply(SeatTypeEnum.RW.getVal()).multiply(TrainTypeEnum.getPrice(train.getType())));
                dailyTrainTicket.setYw(hardSleeper);
                dailyTrainTicket.setYwPrice(sumKm.multiply(SeatTypeEnum.YW.getVal()).multiply(TrainTypeEnum.getPrice(train.getType())));
                dailyTrainTicket.setCreateTime(now);
                dailyTrainTicket.setUpdateTime(now);
                // dailyTrainTicketMapper.insert(dailyTrainTicket);
                dailyTrainTicketList.add(dailyTrainTicket);
            }
        }
        dailyTrainTicketMapper.insertBacth(dailyTrainTicketList);
    }

    /**
     * 查询座位余票
     * @param date
     * @param trainCode
     * @param type
     * @return
     */
    public Long countSeat(Date date, String trainCode, String type) {
        DailyTrainSeatExample dailyTrainSeatExample = new DailyTrainSeatExample();
        dailyTrainSeatExample.createCriteria()
                        .andDateEqualTo(date)
                        .andTrainCodeEqualTo(trainCode)
                        .andSeatTypeEqualTo(type);
        long countByExample = dailyTrainSeatMapper.countByExample(dailyTrainSeatExample);
        if (countByExample == 0) {
            return -1L;
        } else {
            return countByExample;
        }
    }
    @Override
    public DailyTrainTicket selectByUniqueKey(Date date, String trainCode, String start, String end) {
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.createCriteria()
                .andDateEqualTo(date)
                .andTrainCodeEqualTo(trainCode)
                .andStartEqualTo(start)
                .andEndEqualTo(end);
        List<DailyTrainTicket> dailyTrainTickets = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);
        if (CollUtil.isEmpty(dailyTrainTickets)) {
            return null;
        } else {
            return dailyTrainTickets.get(0);
        }
    }
}